#region File Description
///////////////////////////////////////////////////////////////////////////////
/// \file Ecosystem.cs
/// \brief This file stores the Ecosystem class
/// \note This should be sublclassed in application to provide loading and saving functionality
/// \author Bradley Mclain
/// \date 15/5/2010
/// \remarks Copyright(c) 2010 LM01 Project Group (Animus Games - ViralFlux)
/// \remarks Some Rights Reserved.
/// Licenced under: Microsoft Reciprocal License (Ms-RL)
/// For More Information see: www.microsoft.com/opensource/licenses.mspx
///////////////////////////////////////////////////////////////////////////////
#endregion

#region Using Statements
    using System.Collections.Generic;
#endregion

namespace PropagationEngine
{
    /// <summary>
    /// \class Ecosystem
    /// \brief This class provides the basis for the PropagationEngine
    /// \note It should be subclassed in application
    /// \author Bradley Mclain
    /// \date 15/5/2010
    /// </summary>
    public abstract class Ecosystem
    {
        #region Attributes

        static protected Dictionary<int, Node> nodes;
        static protected List<Edge> edges;
        static public Dictionary<int, Entity> entities;
        static protected internal Ruleset ruleset { get; set; } // pfft. I don't play by the rules.

        #endregion

        #region Methods

        /// <summary>
        /// \author Bradley Mclain
        /// \brief Constructor for Ecosystem
        /// \date 15/05/2010
        /// </summary>
        protected Ecosystem()
        {
            nodes = new Dictionary<int, Node>();
            edges = new List<Edge>();
            entities = new Dictionary<int, Entity>();
        }

        /// <summary>
        /// \author Bradley Mclain
        /// \brief Function responsible for running one iteration of the engine
        /// \date 15/5/2010
        /// </summary>
        public static void Tick()
        {
            //Reset counts before each tick
            foreach (KeyValuePair<int, Entity> e in entities)
                e.Value.Count = 0;

            //Needs to make a call to the tick1
            foreach (KeyValuePair<int, Node> kvp in nodes)
                kvp.Value.Tick1();

            //Needs to call tick of every edge
            foreach (Edge edge in edges)
                edge.Tick();

            //Needs to make a call to the tick2 and tick3 of every node
            foreach (KeyValuePair<int, Node> kvp in nodes)
            {
                kvp.Value.Tick2();
                kvp.Value.Tick3();
            }
            
        }

        /// \brief Resets and Clears the Entire Ecosystem
        /// \note Resets by clearing the Edge, Node and Entity Lists
        /// \note This destroys all the Nodes and Edges
        /// \author Steven Duda
        public static void Reset()
        {
            edges.Clear();
            nodes.Clear();
            entities.Clear();
        }

        /// \brief Clears all Entities from the Ecosystem
        /// \note Leaves the Node and Edge System in tact
        /// \author Steven Duda
        public static void Clear()
        {
            entities.Clear();

            //Needs to make a call to the tick and tock of every node
            foreach (KeyValuePair<int, Node> kvp in nodes)
                kvp.Value.Clear();

            //Needs to call tick of every edge
            foreach (Edge edge in edges)
                edge.Clear();
        }

        /// <summary>
        /// \author Bradley Mclain
        /// \brief Load an Ecosystem from the given XML file
        /// \note Should be overridden in application
        /// \date 15/05/2010
        /// </summary>
        public abstract bool LoadFromXML(string filename);

        /// <summary>
        /// \author Bradley Mclain
        /// \brief Load an Ecosystem to the given binary file
        /// \note Should be overridden in application
        /// \date 15/05/2010
        /// </summary>
        public abstract bool LoadFromBinary(string filename);

        /// <summary>
        /// \author Bradley Mclain
        /// \brief Save an Ecosystem to the given file in XML
        /// \note Should be overridden in application
        /// \date 15/05/2010
        /// </summary>
        public abstract void SaveToXML(string filename);

        /// <summary>
        /// \author Bradley Mclain
        /// \brief Save an Ecosystem to the given file in binary
        /// \note Should be overridden in application
        /// \date 15/05/2010
        /// </summary>
        public abstract void SaveToBinary(string filename);

        /// <summary>
        /// \brief Use this function to retrieve the node reference for a given ID
        /// \author Bradley Mclain
        /// \param id The id of the desired node
        /// \return The node if found, otherwise null
        /// \date 15/05/2010
        /// </summary>
        public static Node GetNodeByID(int id)
        {
            if (nodes.ContainsKey(id))
                return Ecosystem.nodes[id];
            else
                return (new Node());
        }

        /// <summary>
        /// \brief Use this function to retrieve an entity reference for a given ID
        /// \author Bradley Mclain
        /// \param id The id of the desired entity
        /// \return The entity if found, otherwise null
        /// \date 15/05/2010
        /// </summary>
        public static Entity GetEntityByID(int id)
        {
            return Ecosystem.entities[id];
        }

        /// <summary>
        /// \author Bradley Mclain
        /// \brief Helper function which fetches all of the incoming edges for a given node
        /// \param node The node to fetch edges for
        /// \return List of incoming edges
        /// \date 15/05/2010
        /// </summary>
        public static List<Edge> GetIncomingEdgesForNode(Node node)
        {
            List<Edge> incoming = new List<Edge>();

            foreach (Edge edge in Ecosystem.edges)
            {
                //If ends in node then it is incoming
                if(edge.EndNode.ID == node.ID)
                {
                    incoming.Add(edge);
                }
            }

            return incoming;
        }

        /// <summary>
        /// \author Bradley Mclain
        /// \brief Helper function which fetches all of the outgoing edges for a given node
        /// \param node The node to fetch edges for
        /// \return List of outgoing edges
        /// \date 15/05/2010
        /// </summary>
        public static List<Edge> GetOutgoingEdgesForNode(Node node)
        {
            List<Edge> outgoing = new List<Edge>();

            foreach (Edge edge in Ecosystem.edges)
            {
                //If ends in node then it is incoming
                if (edge.StartNode.ID == node.ID)
                {
                    outgoing.Add(edge);
                }
            }

            return outgoing;
        }

        #endregion
    }
}
